from enum import Enum
from datetime import date
from typing import List

class OrderStatus(Enum):
    CREATE = 1
    PAID = 2
    SHIPPING = 3
    DELIVERED = 4
    CANCEL = 5

class Customer:
    def __init__(self, name: str, contact: str, address: str, active: bool = True):
        self.name = name
        self.contact = contact
        self.deliveryAddress = address
        self.active = active
        self.orders: List[Order] = []

    def place_order(self, order: 'Order'):
        self.orders.append(order)

class Product:
    def __init__(self, title: str, weight: float, description: str, price: float):
        self.title = title
        self.weight = weight
        self.description = description
        self._price = price

    def getPriceForQuantity(self, quantity: int) -> float:
        return self._price * quantity

    def getWeight(self) -> float:
        return self.weight


class OrderDetail:
    def __init__(self, product: Product, quantity: int):
        self.quantity = quantity
        self.product = product

    def calculateSubTotal(self) -> float:
        return self.product.getPriceForQuantity(self.quantity)

    def calculateWeight(self) -> float:
        return self.product.getWeight() * self.quantity


class Order:
    def __init__(self, customer: Customer, date_created: date):
        self.customer = customer
        self.createDate = date_created
        self.status = OrderStatus.CREATE
        self._details: List[OrderDetail] = []
        self.payments: List[Payment] = []
        customer.place_order(self)

    def add_detail(self, detail: OrderDetail):
        if detail not in self._details:
            self._details.append(detail)

    def add_payment(self, payment: 'Payment'):
        self.payments.append(payment)
        self.status = OrderStatus.PAID

class Payment:
    def __init__(self, amount: float):
        self.amount = amount


class Credit(Payment):
    def __init__(self, amount: float, number: str, type: str, expireDate: date):
        super().__init__(amount)
        self.number = number
        self.type = type
        self.expireDate = expireDate


class Cash(Payment):
    def __init__(self, amount: float, cashTendered: float):
        super().__init__(amount)
        self.cashTendered = cashTendered


class WireTransfer(Payment):
    def __init__(self, amount: float, bankID: str, bankName: str):
        super().__init__(amount)
        self.bankID = bankID
        self.bankName = bankName


class AliPay(Payment):
    def __init__(self, amount: float, number: str):
        super().__init__(amount)
        self.number = number


class WeixinPay(Payment):
    def __init__(self, amount: float, number: str):
        super().__init__(amount)
        self.number = number